#include "ThirdPartyGuarantee.h"

#include <iostream>
#include <sstream>

#include "BondContainer.h"

CThirdPartyGuarantee& CThirdPartyGuarantee::instance() {
  static CThirdPartyGuarantee s_tpg;
  return s_tpg;
}

CThirdPartyGuarantee::CThirdPartyGuarantee() {
  m_nationalMap.clear();
  m_nationalMap[CBondContainer::TPGCBIC] = {"Z000348"};
  m_nationalMap[CBondContainer::TPGCSCI] = {"Z001152", "S001527"};
  m_nationalMap[CBondContainer::TPGIG] = {"Z000256"};
  m_nationalMap[CBondContainer::TPGSinoguarantee] = {"Z000649"};
  m_nationalMap[CBondContainer::TPGHanHuaGuarantee] = {"H000259"};

  m_setArea.insert({"重庆", "江苏", "四川", "安徽", "广东", "全国性"});
}

CThirdPartyGuarantee::~CThirdPartyGuarantee() { ClearData(); }

void CThirdPartyGuarantee::UpdateData(xQBThirdPartyGuaranteeListAck_c* pAck) {
  if (!pAck) {
    return;
  }

  std::lock_guard<std::mutex> locker(m_mutex);
  std::string combBondKey;
  for (auto it = pAck->m_List.begin(); it != pAck->m_List.end(); ++it) {
    combBondKey =
        std::string(it->m_bondkey) + "." + std::string(it->m_listedmarket);
    m_mapData[combBondKey] = *it;
  }
}

void CThirdPartyGuarantee::ClearData() { m_mapData.clear(); }

bool CThirdPartyGuarantee::CheckBond(int bondIndex, const BLHCONDITION& cond) {
  if (cond.nThirdPartyGuarantee[0] == CBondContainer::TPGAll) {
    return true;
  }

  std::string combBondKey = GetCombBondKey(bondIndex);
  if (combBondKey == "") {
    return false;
  }

  std::lock_guard<std::mutex> locker(m_mutex);
  auto it = m_mapData.find(combBondKey);
  if (it != m_mapData.end()) {
    const QBThirdPartyGuarantee& tpg = it->second;
    for (int i = 0; i < sizeof(cond.nThirdPartyGuarantee) / sizeof(UINT); i++) {
      int type = cond.nThirdPartyGuarantee[i];
      if (IsNationalGuarantee(type, tpg)) {
        return true;
      }
      if (IsRegionalGuarantee(type, tpg)) {
        return true;
      }
    }
  }
  return false;
}

bool CThirdPartyGuarantee::IsNationalGuarantee(
    int type, const QBThirdPartyGuarantee& tpg) {
  if (!IsNationalGuaranteeType(type)) {
    return false;
  }

  const InstitutionCodeList& lst = ToInstitutionCode(type);
  for (size_t i = 0; i < lst.size(); i++) {
#ifdef WIN32
    if (stricmp(tpg.m_institution_code, lst[i]) == 0) {
#else
    if (strcasecmp(tpg.m_institution_code, lst[i]) == 0) {
#endif
      return true;
    }
  }
  return false;
}

bool CThirdPartyGuarantee::IsNationalGuaranteeType(int type) const {
  return (type >= CBondContainer::TPGCBIC &&
          type <= CBondContainer::TPGHanHuaGuarantee);
}

const CThirdPartyGuarantee::InstitutionCodeList&
CThirdPartyGuarantee::ToInstitutionCode(int type) const {
  auto iter = m_nationalMap.find(type);
  if (iter != m_nationalMap.end()) {
    return iter->second;
  }
  static InstitutionCodeList lst;
  return lst;
}

bool CThirdPartyGuarantee::IsRegionalGuarantee(
    int type, const QBThirdPartyGuarantee& tpg) {
  if (!IsRegionalGuaranteeType(type)) {
    return false;
  }

  if (IsOtherArea(type, tpg.m_area)) {
    return true;
  }

  const char* area = ToArea(type);
  QString strArea = QString::fromUtf8(area);
  QString strArea2 = QString::fromLocal8Bit(tpg.m_area);
  if (strArea.length() > 0) {
    if (strArea.compare(strArea2) == 0) {
      return true;
    }
  }
  return false;
}

bool CThirdPartyGuarantee::IsRegionalGuaranteeType(int type) const {
  return (type >= CBondContainer::TPGChongQing &&
          type <= CBondContainer::TPGOthers);
}

bool CThirdPartyGuarantee::IsOtherArea(int type, const char* area) const {
  if (type == CBondContainer::TPGOthers) {
    QString strArea = QString::fromLocal8Bit(area);
    for (auto it = m_setArea.begin(); it != m_setArea.end(); ++it) {
      QString strArea2 = QString::fromUtf8((*it).c_str());
      if (strArea.compare(strArea2) == 0) {
        return true;
      }
    }
  }

  return false;
}

const char* CThirdPartyGuarantee::ToArea(int type) const {
  switch (type) {
    case CBondContainer::TPGChongQing:
      return "重庆";
    case CBondContainer::TPGJiangSu:
      return "江苏";
    case CBondContainer::TPGSiChuan:
      return "四川";
    case CBondContainer::TPGAnHui:
      return "安徽";
    case CBondContainer::TPGGuangDong:
      return "广东";
    default:
      return "";
  }

  return "";
}

std::string CThirdPartyGuarantee::GetCombBondKey(int bondIndex) const {
  CBondContainer& bc = CBondContainer::instance();
  if (bc.IsValidIndex(bondIndex)) {
    const CBondInfo& bi = bc.ElementAtR(bondIndex);
    return bi.GetCombBondKey();
  }
  return "";
}
